<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2023 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2023-06-25 10:55:00
// +----------------------------------------------------------------------

declare (strict_types=1);

namespace buwang\command;


use buwang\util\console\CliEcho;
use Phinx\Util\Util;
use think\console\Input;
use think\console\input\Argument as InputArgument;
use think\console\Output;
use think\migration\command\migrate\Create;
use think\exception\InvalidArgumentException;
use RuntimeException;

class MigrateCreateCommand extends Create
{
    //应用目录名
    protected $app_name;

    protected function configure()
    {
        // 指令配置
        $this->setName('mn-migrate:create')
            ->setDescription('Create a new migration')
            ->addArgument('app_name', InputArgument::REQUIRED, 'the module where you create')
            ->addArgument('name', InputArgument::REQUIRED, 'What is the name of the migration?')
            ->setHelp(sprintf('%sCreates a new database migration%s', PHP_EOL, PHP_EOL));
    }

    protected function execute(Input $input, Output $output)
    {
        $this->app_name = $input->getArgument('app_name');
        $className = $input->getArgument('name');

        try {
            $path = $this->create($className);
            $output->writeln("Command executed successfully ".  str_replace(getcwd(), '', realpath($path)));
        } catch (\Exception $e) {
            $output->writeln("Command failed " . $e->getMessage());
        }
    }

    /**
     * @param string $className
     * @return string
     */
    protected function create(string $className): string
    {
        $path = $this->ensureDirectory();

        if (!Util::isValidPhinxClassName($className)) {
            throw new InvalidArgumentException(sprintf('The migration class name "%s" is invalid. Please use CamelCase format.', $className));
        }

        if (!Util::isUniqueMigrationClassName($className, $path)) {
            throw new InvalidArgumentException(sprintf('The migration class name "%s" already exists', $className));
        }

        // Compute the file path
        $fileName = Util::mapClassNameToFileName($className);
        $filePath = $path . DIRECTORY_SEPARATOR . $fileName;

        if (is_file($filePath)) {
            throw new InvalidArgumentException(sprintf('The file "%s" already exists', $filePath));
        }

        // Verify that the template creation class (or the aliased class) exists and that it implements the required interface.
        $aliasedClassName = null;

        // Load the alternative template if it is defined.
        $contents = file_get_contents($this->getTemplate());

        // inject the class names appropriate to this migration
        $contents = strtr($contents, [
            'MigratorClass' => $className,
        ]);

        if (false === file_put_contents($filePath, $contents)) {
            throw new RuntimeException(sprintf('The file "%s" could not be written to', $path));
        }

        return $filePath;
    }

    /**
     * @return string
     */
    protected function ensureDirectory(): string
    {
        $path = $this->app->getAppPath() . $this->app_name . DS . 'database' . DS . 'migrations';

        if (!is_dir($path) && !mkdir($path, 0755, true)) {
            throw new InvalidArgumentException(sprintf('directory "%s" does not exist', $path));
        }

        if (!is_writable($path)) {
            throw new InvalidArgumentException(sprintf('directory "%s" is not writable', $path));
        }

        return $path;
    }

    /**
     * @return string
     */
    protected function getTemplate(): string
    {
        return __DIR__ . '/stubs/migrate.stub';
    }

}
